﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ControlAccessUser.Model;

namespace ControlAccessUser.Bussiness
{
    public static class ManagerUser
    {
        
        public static Model.User GetUserByUserNameAndUserPassword(Model.User UserToVerify)
        {
            if (!string.IsNullOrEmpty(UserToVerify.UserName) && !string.IsNullOrEmpty(UserToVerify.UserPassword))
            {
                ICollection<Model.User> UserList = DataAccess.DataAccessUser.SearchUserByUserNameAndUserPassword(UserToVerify);
                if (UserList.Count == 1)
                {
                    RegisterLoginUser(new Login() { DataTimeLoginUser = DateTime.Now, DataTimeLogoutUser = null, User = UserList.First() });
                    return UserList.First();
                }
                else
                {
                    throw new Exception(Message.LoginError);
                }
            }
            else
            {
                throw new Exception(Message.NullOrEmptyFields);
            }
            
        }

        public static void RegisterUser(Model.User NewUser)
        {
            if (!string.IsNullOrEmpty(NewUser.UserFirstName) && !string.IsNullOrEmpty(NewUser.UserLastName) && !string.IsNullOrEmpty(NewUser.UserName) && !string.IsNullOrEmpty(NewUser.UserPassword))
            {
                ICollection<Model.User> UserExist = DataAccess.DataAccessUser.SearhcUserByUserName(NewUser);
                if (UserExist.Count() == 0)
                {
                    DataAccess.DataAccessUser.InsertNewUser(NewUser);
                    DataAccess.ControlAccessUserEntities.Instance.SaveChanges();
                }
                else
                {
                    throw new Exception(Message.UserAlreadyExist);
                }
            }
            else
            {
                throw new Exception(Message.NullOrEmptyFields);
            }            
            
        }

        public static string ValidateUserName(User user)
        {
            if (user.UserName.Contains(" "))
                throw new Exception();
            else
                return user.UserName;
        }

        public static void RegisterLoginUser(Model.Login Login)
        {
            ICollection<Login> Log = DataAccess.DataAccessLogin.SearchLastRegisterLogin(Login.User);
            if (Log.Count == 0)
            {
                DataAccess.DataAccessLogin.InsertNewLogin(Login);
            }
            else
            {
                if (Log.First().DataTimeLogoutUser != null)
                {
                    DataAccess.DataAccessLogin.InsertNewLogin(Login);
                }
            }            
        }

        public static void RegisterLogout(User User)
        {
            DataAccess.DataAccessLogin.RegisterLogout(User);
        }

        public static ICollection<User> SearhcUserByUserName(User User)
        {
            return DataAccess.DataAccessUser.SearhcUserByUserName(User);
        }

        public static ICollection<User> SearchUserByUserId(User User)
        {
            return DataAccess.DataAccessUser.SearchUserByUserId(User);
        }

        public static ICollection<User> SearchUserByRelativeFields(User User)
        {
            return DataAccess.DataAccessUser.SearchUserByRelativeFields(User);
        }


        
        public static ICollection<ItemReport> SearchLoginsByUserAndSession(User User, DateTime DateTimeInit, DateTime DateTimeEnd)
        {
            ICollection<Login> logins=DataAccess.DataAccessLogin.SearchLoginsByUserAndSession(User, DateTimeInit, DateTimeEnd);
            ICollection<ItemReport> items = CalculateTimeSpanWorkedByHours(User, logins);
            return items;
        }

        private static ICollection<ItemReport> CalculateTimeSpanWorkedByHours(User User, ICollection<Login> logins)
        {
            ICollection<ItemReport> items = new List<ItemReport>();
            foreach (Login l in logins)
            {
                items.Add(new ItemReport() { User = User, HoursToWorks =((TimeSpan) (l.DataTimeLogoutUser-l.DataTimeLoginUser)).TotalHours, DateTimeInit=l.DataTimeLoginUser, DateTimeEnd=(DateTime)l.DataTimeLogoutUser, AmountLogins=1, DaysWork=1 });
            }
            return items;
        }

        public static ICollection<ItemReport> SearchLoginsByUserAndWeek(User User, DateTime DateTimeInit, DateTime DateTimeEnd)
        {
            ICollection<Login> logins = DataAccess.DataAccessLogin.SearchLoginsByUserAndSession(User, DateTimeInit, DateTimeEnd);
            ICollection<ItemReport> items = CalculateTimeSpanWorkedByHours(User, logins);
            items = GroupByWeek(User, items, DateTimeInit, DateTimeEnd);
            return items;
        }

        private static ICollection<ItemReport> GroupByWeek(User User, ICollection<ItemReport> items, DateTime DateTimeInit, DateTime DateTimeEnd)
        {
            ICollection<ItemReport> Result = new List<ItemReport>();
            int AmountDays = ((int)((TimeSpan)(DateTimeEnd - DateTimeInit)).TotalDays);
            int DaysOfWeek;
            while(AmountDays>0)
            {
                if (DateTimeInit.AddDays(7) <= (DateTimeEnd))
                {
                    DaysOfWeek = 7;
                    AmountDays = AmountDays - 7 ;
                }
                else
                {
                    DaysOfWeek = AmountDays;
                    AmountDays = 0;
                }                    
                double hours = 0;
                int AmountLogins = 0;
                foreach (ItemReport Item in items)
                {
                    if (IsInsideDate(Item, DateTimeInit, DateTimeInit.AddDays(DaysOfWeek)))
                    {
                        hours = hours + Item.HoursToWorks;
                        AmountLogins++;
                    }
                }
                if (hours>0)
                {
                    Result.Add(new ItemReport() { DateTimeInit = DateTimeInit, DateTimeEnd = DateTimeInit.AddDays(DaysOfWeek), DaysWork = (int)(hours / 24), HoursToWorks = hours, User = items.ElementAt(0).User, AmountLogins = AmountLogins });
                }
                DateTimeInit = DateTimeInit.AddDays(DaysOfWeek);
            }
                
            return Result;
        }

        private static bool IsInsideDate(ItemReport Item, DateTime DateTimeInit, DateTime DateTimeEnd)
        {
            if (Item.DateTimeInit.Date >= DateTimeInit.Date && Item.DateTimeInit<=DateTimeEnd.Date)
            { 
                return true;
            }
            else
            {
                return false;
            }
        }


        public static ICollection<ItemReport> SearchLoginsByUserAndMonth(User User, DateTime DateTimeInit, DateTime DateTimeEnd)
        {
            ICollection<Login> logins = DataAccess.DataAccessLogin.SearchLoginsByUserAndSession(User, DateTimeInit, DateTimeEnd);
            ICollection<ItemReport> items = CalculateTimeSpanWorkedByHours(User, logins);
            items = GroupByMonth(User, items, DateTimeInit, DateTimeEnd);
            return items;
        }

        private static ICollection<ItemReport> GroupByMonth(User User, ICollection<ItemReport> items, DateTime DateTimeInit, DateTime DateTimeEnd)
        {
            ICollection<ItemReport> Result = new List<ItemReport>();
            int AmountDays = ((int)((TimeSpan)(DateTimeEnd - DateTimeInit)).TotalDays);
            int DaysOfMonth;
            while(AmountDays>0)
            {
                if (DateTimeInit.AddDays(30) <= (DateTimeEnd))
                {
                    DaysOfMonth = 30;
                    AmountDays = AmountDays - 30;
                }
                else
                {
                    DaysOfMonth = AmountDays;
                    AmountDays = 0;
                }                    
                double hours = 0;
                int AmountLogins = 0;
                foreach (ItemReport Item in items)
                {
                    if (IsInsideDate(Item, DateTimeInit, DateTimeInit.AddDays(DaysOfMonth)))
                    {
                        hours = hours + Item.HoursToWorks;
                        AmountLogins++;
                    }
                }
                if (hours>0)
                {
                    Result.Add(new ItemReport() { DateTimeInit = DateTimeInit, DateTimeEnd = DateTimeInit.AddDays(DaysOfMonth), DaysWork = (int)(hours / 24), HoursToWorks = hours, User = items.ElementAt(0).User, AmountLogins = AmountLogins });
                }
                DateTimeInit = DateTimeInit.AddDays(DaysOfMonth);
            }
                
            return Result;
        }

        public static string RegisterEntryOrExitUser(User UserToVerify)
        {
            string Result = "";
            if (!string.IsNullOrEmpty(UserToVerify.UserName) && !string.IsNullOrEmpty(UserToVerify.UserPassword))
            {
                ICollection<Model.User> UserList = DataAccess.DataAccessUser.SearchUserByUserNameAndUserPassword(UserToVerify);
                if (UserList.Count == 1)
                {
                    ICollection<Model.Login> Login = DataAccess.DataAccessLogin.SearchLastRegisterLogin(UserList.First());
                    if (Login.Count == 0)
                    {
                        RegisterLoginUser(new Login() { DataTimeLoginUser = DateTime.Now, DataTimeLogoutUser = null, User = UserList.First() });
                        Result = Message.RegisterLoginSuccessfully;
                    }
                    else
                    {
                        if (Login.First().DataTimeLogoutUser != null)
                        {
                            RegisterLoginUser(new Login() { DataTimeLoginUser = DateTime.Now, DataTimeLogoutUser = null, User = UserList.First() });
                            Result = Message.RegisterLoginSuccessfully;
                        }
                        else
                        {
                            RegisterLogout(UserList.First());
                            Result = Message.RegisterLogoutSuccessfully;
                        }
                    }
                }
                else
                {
                    throw new Exception(Message.LoginError);
                }
            }
            else
            {
                throw new Exception(Message.NullOrEmptyFields);
            }
            return Result;
        }
    }
}
